# MakeBy: LiuBoyuan
import os
import time
from typing import NoReturn

import jwt
from fastapi.encoders import jsonable_encoder
from sqlalchemy import and_, func
from sqlalchemy.orm import Session

from Config import Config
from Model import UserModel
from Schema.UserSchema import UserFormSchema, tokenMixin, UserSchema
from Service.Base import BaseService


class UserLoginService:
    def MakeToken(self, userFormSchema: UserFormSchema):
        """
        为传来的数据生成一个token
        :param userFormSchema:
        :return:
        """
        username = userFormSchema.username
        salt = Config.TokenConfig.SALT
        after = time.time() + 3600 * 24

        payload = {
            "username": username,
            "exp": after,
        }
        return jwt.encode(payload=payload, key=salt, algorithm="HS256")

    def getUserToken(self, token, session):
        """
        通过Token获取到User
        :param token:
        :param session:
        :return:
        """

        try:
            payload: dict = jwt.decode(token, key=Config.TokenConfig.SALT, algorithms="HS256")
        except jwt.DecodeError as e:
            print(type(token))
            print("token不正确", e)
            return False
        except jwt.exceptions.ExpiredSignatureError as e:  # token 过期
            return False
        username = payload.get("username")
        try:
            datas = UserServeiceInstance.getByDict({
                "username": username,
            }, session)
            print(type(datas[0]))
            return datas[0]
        except Exception as e:
            print(f"不存在用户{e}")
            return False

    def ValidateToken(self, token, session):
        """
        验证传来的token是否为注册了用户的
        :param token:
        :return:
        """
        return bool(self.getUserToken(token, session))


class UserService(BaseService):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.TokenInstance = UserLoginService()

    def Login(self, userFormSchema: UserFormSchema, session: Session) -> bool:

        self.model: UserModel
        model = session.query(self.model).filter(and_(func.binary(userFormSchema.username) == self.model.username,
                                                      func.binary(
                                                          userFormSchema.password) == self.model.password)).first()
        if model is None:
            model = session.query(self.model).filter(
                func.binary(userFormSchema.username) == self.model.username).first()
            if model is None:
                return "regedit"
            else:
                return False, None
        token = self.TokenInstance.MakeToken(userFormSchema)

        return True, token, model

    def Reg(self, userFormSchema: UserFormSchema, session: Session) -> NoReturn:
        self.add(userFormSchema, session)

    def validateToken(self, tokenmixin: tokenMixin, session: Session) -> bool:
        return self.TokenInstance.ValidateToken(tokenmixin.token, session)

    def getUserByToken(self, tokenmixin: tokenMixin, session: Session) -> UserSchema:
        return self.TokenInstance.ValidateToken(tokenmixin.token, session)

    def get_topoffset(self, token: str, session: Session):
        user = self.TokenInstance.getUserToken(token, session)
        if not user:
            return ""
        model = jsonable_encoder(user)
        userSchema = UserSchema(**model)
        return userSchema.offset_top

    async def topoffset(self, token, session, offset):
        user = self.TokenInstance.getUserToken(token, session)
        if not user:
            return False
        model = jsonable_encoder(user)
        userSchema = UserSchema(**model)
        userSchema.offset_top = offset
        self.update(session, userSchema)

    async def uploadTopImage(self, token, session, file):
        user = self.TokenInstance.getUserToken(token, session)
        if not user:
            return False
        model = jsonable_encoder(user)
        userSchema = UserSchema(**model)
        filename = userSchema.username + file.filename
        userSchema.user_top_image = filename

        with open(os.path.join(Config.File.top_path, filename), "wb") as f:
            f.write(await file.read())
        self.update(session, userSchema)

    async def uploadHeaderImage(self, token, session, file):
        user = self.TokenInstance.getUserToken(token, session)
        if not user:
            return False
        model = jsonable_encoder(user)
        userSchema = UserSchema(**model)
        filename = userSchema.username + file.filename

        userSchema.headimage = filename
        with open(os.path.join(Config.File.head_path, filename), "wb") as f:
            f.write(await file.read())
        self.update(session, userSchema)

    async def HeadImage(self, token, session):
        user = self.TokenInstance.getUserToken(token, session)
        if not user:
            return False
        model = jsonable_encoder(user)
        userSchema = UserSchema(**model)
        return userSchema.headimage

    async def TopImage(self, token, session):
        user = self.TokenInstance.getUserToken(token, session)
        if not user:
            return False
        model = jsonable_encoder(user)
        userSchema = UserSchema(**model)
        return userSchema.user_top_image


UserServeiceInstance = UserService(UserModel, "user")
